package action;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;

import org.json.JSONObject;

import utils.AjaxResult;
import utils.PagingParams;

public class AjaxPagingAction extends BaseAction {
        
    // 与分页相关的变量    
    private int resultsCount;            /* 总记录数 */
    private static int recordsPerPage;/* 每页显示的记录数 */
    private static int numbersPerPage;/* 每页显示的页码数 */
    private int pageNum;                /* 页数 */
    private int currentPage;            /* 当前页码 */
    private String firstPage;            /* 首页，页码栏元素 */
    private String lastPage;            /* 尾页，页码栏元素 */
    private String previousPage;        /* 上一页，页码栏元素 */
    private String nextPage;            /* 下一页，页码栏元素 */
    private String normalPage;            /* 常规页码栏，页码栏元素 */
    private String currentPageInfo;    /* 当前所处页信息，页码栏元素 */
    private String pageLift;            /* 分页跳转元素，页码栏元素 */
    private String pagingSource;        /* 分页源 */
    private String extraRequestParams; /* 请求中已有的参数 */
    private JSONObject obj;            /* 返回结果 */
    
    // 内置对象
    private String path;
    private String basePath;
        
    public String execute() {
        obj = new JSONObject();
        
        /* 获得分页源 */
        pagingSource = (String) session.getAttribute(PagingParams.PAGING_SOURCE);
        
        // 设定每页记录
        int counts = (Integer) session.getAttribute(PagingParams.PAGING_PARAM_COUNTS_PER_PAGE);
        setRecordsPerPage(counts);
        
        // 设定每页显示的页码数
        setNumbersPerPage(PagingParams.PAGES_PER_PAGE);
    
        // 设定所有结果数
        setResultsCount((Integer)session.getAttribute(PagingParams.RESULT_SET_TOTAL_SIZE));
        
        // 计算并设定页数
        setPageNum();
            
        // 设定当前页码
        setCurrentPage((Integer) session.getAttribute(PagingParams.CURRENT_PAGE));
            
        // 设定请求链接中已有的参数
        setExtraRequestParams();
        
        // 设定查询结果
        setResults();
        
        // 设定页码栏
        setPageBar();
            
        AjaxResult result = new AjaxResult(AjaxResult.CODE_SUCCESS, "success");
        result.addData("result",  obj.toString());
        try {
            inputStream = new ByteArrayInputStream(result.toString().getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        
        return pagingSource;
            
    }
    
    private void setResults() {
        String result = (String) session.getAttribute(PagingParams.PAGING_RESULT_AJAX_RESULT);
        obj.put(PagingParams.AJAX_QUERY_RESULT, result);
    }

    /**
     * 设定已有的请求参数
     */
    private void setExtraRequestParams() {
        String params = (String) session.getAttribute(PagingParams.EXTRA_REQUEST_PARAMS);
        if (params == null || "".equals(params.trim())) {
            setExtraRequestParams("");
        } else {
            setExtraRequestParams(params);
        }
    }
    
    /**
     * 设定所有结果数
     * @param count 所有结果数
     */
    private void setResultsCount(int count) {
        this.resultsCount = count;
    }
        
    /**
     * 设定页码数
     */
    private void setPageNum() {
        int page = resultsCount % recordsPerPage;
        int pages = resultsCount / recordsPerPage;
        int pageNum = (page==0)?pages:(pages + 1);
    
        setPageNum(pageNum);
    }
        
    /**
     * 设定页码栏
     * 每页显示的页码数多于结果页数时， 显示全部页码
     * 每页显示的页码数少于结果页数时， 显示部分页码， 且当前页码尽量位于中间位置
     */
    private void setPageBar() {
        setFirstPage();
        setNormalPage();
        setLastPage();
        setPreviousPage();
        setNextPage();
        setCurrentPageInfo();
        setPageLift();
    }
        
    /**
     * 设定页码栏中的 "首页" 链接
     */
    public void setFirstPage() {
        // 设定 链接是否可用
        if (numbersPerPage < pageNum && currentPage > numbersPerPage / 2 + 1) {
            setFirstPage("<li><a onclick=\"ajaxGet(1, '" +
                    this.getExtraRequestParams() +"')\">首页</a></li>");
        } else {
            setFirstPage("<li class=\"disabled\"><a>首页</a></li>");
        }
        obj.put(PagingParams.PAGING_RESULT_FIRST_PAGE, firstPage);
    }
        
    /**
     * 设定页码栏中的 "尾页" 链接
     */
    public void setLastPage() {
        // 设定 链接是否可用
        if (numbersPerPage < pageNum && currentPage <= pageNum - numbersPerPage / 2) {
            setLastPage("<li><a onclick=\"ajaxGet(" + pageNum
                     + ",'" + this.getExtraRequestParams() + "')\">尾页</a></li>");
        } else {
            setLastPage("<li class=\"disabled\"><a>尾页</a></li>");
        }
        obj.put(PagingParams.PAGING_RESULT_LAST_PAGE, lastPage);
    }
    
    /**
     * 设定页码栏中的 常规页码  链接
     */
    public void setNormalPage() {
        int start, end;
        String page = "";
        // 设定常规页码
        if (numbersPerPage >= pageNum) {            // 每页显示的页码数多于结果页数时， 显示全部页码
            start = 1;                            // 每页显示的页码数少于结果页数时， 显示部分页码， 且当前页码尽量位于中间位置
            end = pageNum;
        } else if (currentPage <= (numbersPerPage / 2) + 1) {    // 前半部分从1开始显示
            start = 1;
            end = numbersPerPage;
        } else if (currentPage < pageNum - numbersPerPage / 2 + 1) {    // 中间部分从中间往两边显示
            start = currentPage - numbersPerPage / 2;
            end = currentPage + numbersPerPage / 2;
        } else {                                        // 后半部分显示至末尾页
            start = pageNum - numbersPerPage + 1;
            end = pageNum;
        }
        for (int i=start; i<=end; ++i) {
            if (i == currentPage) {
                page += "<li class='active'><a>" + i + "</a></li>";
            } else {
                page += "<li><a onclick=\"ajaxGet(" + i
                        +",'" + this.getExtraRequestParams() + "')\">" + i + "</a></li>";
            }
        }
        setNormalPage(page);
        obj.put(PagingParams.PAGING_RESULT_NORMAL_PAGE, normalPage);
    }
        
    /**
     * 设定页码栏中的 "上一页" 链接
     */
    public void setPreviousPage() {
        // 设定 链接是否可用
        if (pageNum >= 1) {
            if (currentPage != 1) {
                setPreviousPage("<li><a onclick=\"ajaxGet(" +
                        (currentPage - 1) + ",'" 
                        + this.getExtraRequestParams() + "')\">上一页</a></li>");
            } else {
                setPreviousPage("<li class='disabled'><a>上一页</a></li>");
            }
        }
        obj.put(PagingParams.PAGING_RESULT_PREVIOUS_PAGE, previousPage);
    }
        
    /**
     * 设定页码栏中的 "下一页" 链接
     */
    public void setNextPage() {
        // 设定 链接是否可用
        if (pageNum >= 1) {
            if (currentPage != pageNum) {
                setNextPage("<li><a onclick=\"ajaxGet(" +
                        (currentPage + 1) + ",'" 
                        + this.getExtraRequestParams() + "')\">下一页</a></li>");
            } else {
                setNextPage("<li class='disabled'><a>下一页</a></li>");
            }
        }
        obj.put(PagingParams.PAGING_RESULT_NEXT_PAGE, nextPage);
    }
        
    /**
     * 设定页码栏中的 "当前页面信息" 元素
     */
    public void setCurrentPageInfo() {
        setCurrentPageInfo("第" + currentPage + "/" + pageNum + "页");
        obj.put(PagingParams.PAGING_RESULT_CURRENT_PAGE_INFO, currentPageInfo);
    }
    
    /**
     * 设定页码栏中的 "分页跳转" 元素
     */
    public void setPageLift() {
        String lift = "<select name=\"jump\" onchange=\"ajaxGet(this.value, '" 
                + this.getExtraRequestParams() + "')\">" 
                + selectPages() + "</select>";
        setPageLift(lift);
        obj.put(PagingParams.PAGING_RESULT_PAGE_LIFT_FORM, pageLift);
    }
        
    /**
     * 生成一个下拉列表的代码，其中的选项为查询结果的分页页码
     * @return
     */
    public String selectPages() {
        String pages = "";
        for (int i=1; i<=pageNum; ++i) {
            if (i != currentPage) {
                pages += "<option>" + i + "</option>";
            } else {
                pages += "<option selected=\"selected\">" + i + "</option>";
            }
        }
        return pages;
    }
    
    @Override
    public void setServletRequest(HttpServletRequest request) {
        super.setServletRequest(request);
        this.path = request.getContextPath();
        this.basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    }
    
    /* getters and setters */
    public static int getRecordsPerPage() {
        return recordsPerPage;
    }
    
    public static void setRecordsPerPage(int recordsPerPage) {
        AjaxPagingAction.recordsPerPage = recordsPerPage;
    }

    public static int getNumbersPerPage() {
        return numbersPerPage;
    }

    public static void setNumbersPerPage(int numbersPerPage) {
        AjaxPagingAction.numbersPerPage = numbersPerPage;
    }

    public int getPageNum() {
        return pageNum;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public int getResultsCount() {
        return resultsCount;
    }

    public String getSetPageSource() {
        return pagingSource;
    }

    public void setSetPageSource(String setPageSource) {
        this.pagingSource = setPageSource;
    }

    public String getFirstPage() {
        return firstPage;
    }

    public void setFirstPage(String firstPage) {
        this.firstPage = firstPage;
    }

    public String getLastPage() {
        return lastPage;
    }

    public void setLastPage(String lastPage) {
        this.lastPage = lastPage;
    }

    public String getPreviousPage() {
        return previousPage;
    }

    public void setPreviousPage(String previousPage) {
        this.previousPage = previousPage;
    }

    public String getNextPage() {
        return nextPage;
    }

    public void setNextPage(String nextPage) {
        this.nextPage = nextPage;
    }

    public String getNormalPage() {
        return normalPage;
    }

    public void setNormalPage(String normalPage) {
        this.normalPage = normalPage;
    }

    public String getCurrentPageInfo() {
        return currentPageInfo;
    }

    public void setCurrentPageInfo(String currentPageInfo) {
        this.currentPageInfo = currentPageInfo;
    }

    public String getPageLift() {
        return pageLift;
    }

    public void setPageLift(String pageLift) {
        this.pageLift = pageLift;
    }

    public String getExtraRequestParams() {
        return extraRequestParams;
    }

    public void setExtraRequestParams(String extraRequestParams) {
        this.extraRequestParams = extraRequestParams;
    }

}